
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.IO;
using System.Collections;
using System.Text.RegularExpressions;

using Swaf;
using Swaf.BizObj;
using Swaf.BizRule;
using Swaf.Config;
using Swaf.Container;
using Swaf.Messaging;

namespace MediaCacheAdmin
{
    /// <summary>
    /// This CSF config partner will process the CsfMessagingMonitorQueue configuration option and setup the
    /// CSF scheduler to monitor an email inbox for incoming media upload emails.
    /// </summary>
    public class MediaUploadManager : IConfigPartner
    {
        protected string m_emailSendTo = "";
        public MediaUploadManager(IApplication app)
        {
        }

        public string EmailSendToAddress { get { return m_emailSendTo; } }
        #region IConfigPartner Members
        public void checkConfigStatus()
        {
        }

        public void registerForConfig(IConfigManager config)
        {
            config.registerHandler("...<EmailUploadOptions>", new EmailUploadOptionsConfigHandler(this));
        }
        #endregion

        protected void setupEmailMonitoring(string msgSys, string msgCon, string schedFreq, string sendTo)
        {
            m_emailSendTo = sendTo;
            Swaf.Call.ICall c2 = new Swaf.Call.RuleMgrCall("processEmailRequest","processEmailRequest");
            QueueConnectionInfo qinfo = new QueueConnectionInfo();
            qinfo.MessagingSystemId = msgSys;
            qinfo.HostName = msgCon;
            qinfo.QueueName = msgCon;
            qinfo.MinThreads = 1;
            qinfo.MaxThreads = 1;
            qinfo.ScheduleInterval = schedFreq;
            IResults rc = Application.currentApp.ruleMgr.execute("CsfMessagingMonitorQueue", new object[] { qinfo, c2, "" });
        }

        public class EmailUploadOptionsConfigHandler : ConfigHandler
        {
            MediaUploadManager m_mgr;
            public EmailUploadOptionsConfigHandler(MediaUploadManager mgr)
            {
                m_mgr = mgr;
            }
            static string[] s_validOptions = new string[] {"messagingSystem", "messagingConnection", "schedulingFrequency", "sendToEmailAddr" };
            public override void executeBefore(IConfigElement configInfo)
            {
                configInfo.checkIllegalAttributes(s_validOptions);
                string msgSys = configInfo.getAttribute("messagingSystem");
                string msgCon = configInfo.getAttribute("messagingConnection");
                string schedFreq = configInfo.getAttribute("schedulingFrequency");
                string sendTo = configInfo.getAttribute("sendToEmailAddr");
                m_mgr.setupEmailMonitoring(msgSys, msgCon, schedFreq, sendTo);
            }
        }
    }

    /// <summary>
    /// The bizrules associated with the media email upload option.
    /// </summary>
	public class MediaUploadBizRules : Syrinx.BaseBizRules
    {
		/// <summary>
		/// 
		/// </summary>
        protected Regex s_sessionRegex = new Regex(@"SessionId=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})");

        /// <summary>
        /// Stores the details of the email upload request into the data access store so that when an incoming email
        /// arrives on the monitored inbox for email upload it can be validated before saving the images in the email.
        /// </summary>
        /// <remarks>
        /// The uploadInfo parameter needs to be populated with the id, emailFrom, uploadDir, sendStatus, uploadUserId,
        /// and requestedDate fields to work properly.
        /// </remarks>
        /// <param name="uploadInfo">The EmailUploadOptions bizobj to be pushed into the data access.</param>
        public void registerEmailUploadRequest(IApplication app, IRuleContext context, IBizObj uploadInfo)
        {
            try
            {
                uploadInfo.put("uploadUser", CurrentUser);
                app.appData.put("Data.MediaCacheAdmin.CreateEmailUploadRequest", uploadInfo);
            }
            catch (Exception e)
            {
                throw new MediaCacheAdminException("Unable to register email upload request", e);
            }
        }

        /// <summary>
        /// When an email message arrives into the inbox being monitored by the schedule and the CSF email messaging
        /// system, this bizrule will get called.  This bizrule will validate that the given email message is
        /// an image upload request and verify it is an authorized email upload via the upload session id that
        /// must be present in the email message body.
        /// </summary>
        /// <remarks>If the email body does not contain match against the s_sessionRegex property of this class,
        /// the email will not be processed.  If it does, the GUID retrieved from the email body must be a valid
        /// id in the EmailUpload data access store.  This rule verifies that the email upload session id has
        /// not been used to upload before and that the email came from the email address the user said it would
        /// come from when they initially made the request via the registerEmailUploadRequest bizrule.
        /// If it turns out that this is a valid email upload of media, the media will be stored in the media cache
        /// specified in the data access store and the upload request will be marked as being processed so that
        /// the session id is no longer valid for future uploads.  The data access store of email upload 
        /// request is not cleared out by this rule so that the requests can be monitored by administrators 
        /// of the application.</remarks>
        /// <param name="msg">The new email that was found in the inbox.</param>
        public void processEmailRequest(IApplication app, IRuleContext context, IMessage msg)
        {
            string txt = msg.MessageText;
            Match m = s_sessionRegex.Match(txt);
            if (m.Success)
            {
                Swaf.BGuid.Guid uploadSessionId = new Swaf.BGuid.Guid(m.Groups[1].Value);
                FlexiMap fm = new FlexiMap();
                fm["id"] = uploadSessionId;
                IBizObjList uploadInfos = app.appData.get("Data.MediaCacheAdmin.GetEmailUploadRequest", fm) as IBizObjList;
                if (uploadInfos != null && uploadInfos.numElements == 1)
                {
                    IBizObj uploadInfo = uploadInfos[0];
                    if (uploadInfo.get("uploadRecieved").Equals(false))
                    {
                        string saveDir = (string)uploadInfo.get("uploadDirectory");
                        IList attachments = msg.getRawProperty("Attachments") as IList;
                        if (attachments != null)
                        {
                            IBizObj image = app.bizObjMgr.create("Image");
                            foreach (IMessageAttachment att in attachments)
                            {
                                image.put("name", Path.Combine(saveDir, att.Name));
                                image.put("data", new Binary(att.Data));
                                IResults rc = app.ruleMgr.execute("addImage", "images", image);

                            }
                        }
                        app.appData.put("Data.MediaCacheAdmin.UpdateEmailUploadRequest", uploadInfo);
                    }

                    if (uploadInfo.get("replyWithStatus").Equals(true))
                    {

                    }
                }
            }
        }
    }
}
